class Layer {
  constructor(method, path, handler) {
    this.method = method;
    this.path = path;
    this.handler = handler;
  }
  match(path, method) {
    // 匹配到这一层
    return this.method === method && this.path === path;
  }
}
class Router {
  constructor() {
    this.stack = []; // 这个是路由站来维护我们创建的路由
  }
  compose(layers, ctx, out) {
    let dispatch = (i) => {
      if (layers.length == i) return out(); // koa中的next方法一定是一个promise
      const handler = layers[i].handler;
      try {
        return Promise.resolve(handler(ctx, () => dispatch(i + 1)));
      } catch (e) {
        return Promise.reject(e);
      }
    };
    return dispatch(0);
  }
  routes() {
    // 插件
    return (ctx, next) => {
      // 调用这个next方法 会走到下一个app.use中
      // 路由中间件可以串联koa中的app.use方法
      let layers = this.stack.filter((layer) =>
        layer.match(ctx.path, ctx.method.toLowerCase())
      );
      return this.compose(layers, ctx, next); // 让路由的层组合好，如果最后一个层也调用了next那么就会执行后续的中间件了
    };
  }
}
["get", "post", "delete", "put"].forEach((method) => {
  Router.prototype[method] = function (path, handler) {
    this.stack.push(new Layer(method, path, handler));
  };
});

module.exports = Router;
